package org.zhaya.sdk.builder;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import org.zhaya.sdk.constant.LogicEnum;
import org.zhaya.sdk.constant.OperatorEnum;

import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * 条件构造器
 *
 * @Author Ryan Yang
 * @Date 2022/9/21 10:26 上午
 */
@Setter
@Getter
public class ConditionsBuilder {

    private String logic;

    private String nodeId;

    private List<Condition> condition;

    public ConditionsBuilder() {
        this.condition = Lists.newArrayList();
    }

    static ConditionsBuilder defBuilder() {
        ConditionsBuilder defBuilder = new ConditionsBuilder();
        defBuilder.setCondition(Collections.singletonList(Condition.builder().field(StrUtil.EMPTY).operator(OperatorEnum.def.name()).value(StrUtil.EMPTY).build()));
        defBuilder.setLogic(LogicEnum.AND.getValue());
        return defBuilder;
    }

    public ConditionsBuilder logic(LogicEnum logic) {
        this.logic = logic.getValue();
        return this;
    }

    void next(String nodeId) {
        this.nodeId = nodeId;
        validate();
    }

    private void validate() {
        Objects.requireNonNull(this.logic, "logic can not be null");
        Objects.requireNonNull(this.nodeId, "nodeId can not be null");
        if (CollUtil.isEmpty(this.condition)) {
            throw new RuntimeException("condition can not be empty");
        }
    }

    public ConditionsBuilder gt(String filedName, Number value) {
        this.condition.add(Condition.builder().field(filedName).value(value).operator(OperatorEnum.gt.name()).build());
        return this;
    }

    public ConditionsBuilder ge(String filedName, Number value) {
        this.condition.add(Condition.builder().field(filedName).value(value).operator(OperatorEnum.gte.name()).build());
        return this;
    }

    public ConditionsBuilder lt(String filedName, Number value) {
        this.condition.add(Condition.builder().field(filedName).value(value).operator(OperatorEnum.lt.name()).build());
        return this;
    }

    public ConditionsBuilder le(String filedName, Number value) {
        this.condition.add(Condition.builder().field(filedName).value(value).operator(OperatorEnum.lte.name()).build());
        return this;
    }

    public ConditionsBuilder eq(String filedName, Number value) {
        this.condition.add(Condition.builder().field(filedName).value(value).operator(OperatorEnum.eq.name()).build());
        return this;
    }

    public ConditionsBuilder eq(String filedName, String value) {
        this.condition.add(Condition.builder().field(filedName).value(value).operator(OperatorEnum.eq.name()).build());
        return this;
    }

    public ConditionsBuilder ne(String filedName, Number value) {
        this.condition.add(Condition.builder().field(filedName).value(value).operator(OperatorEnum.ne.name()).build());
        return this;
    }

    public ConditionsBuilder ne(String filedName, String value) {
        this.condition.add(Condition.builder().field(filedName).value(value).operator(OperatorEnum.ne.name()).build());
        return this;
    }

    public ConditionsBuilder contains(String filedName, String value) {
        this.condition.add(Condition.builder().field(filedName).value(value).operator(OperatorEnum.in.name()).build());
        return this;
    }

    public ConditionsBuilder notContains(String filedName, String value) {
        this.condition.add(Condition.builder().field(filedName).value(value).operator(OperatorEnum.nin.name()).build());
        return this;
    }

    public ConditionsBuilder regexMatch(String filedName, String value) {
        this.condition.add(Condition.builder().field(filedName).value(value).operator(OperatorEnum.reg.name()).build());
        return this;
    }

    public ConditionsBuilder startWith(String filedName, String value) {
        this.condition.add(Condition.builder().field(filedName).value(value).operator(OperatorEnum.startWith.name()).build());
        return this;
    }

    public ConditionsBuilder notBelong(String filedName, String value) {
        this.condition.add(Condition.builder().field(filedName).value(value).operator(OperatorEnum.notBelong.name()).build());
        return this;
    }

    public ConditionsBuilder belong(String filedName, String value) {
        this.condition.add(Condition.builder().field(filedName).value(value).operator(OperatorEnum.belong.name()).build());
        return this;
    }

    public ConditionsBuilder cqlBuilder(String cql) {
        ConditionsBuilder cqlBuilder = new ConditionsBuilder();
        cqlBuilder.setCondition(Collections.singletonList(Condition.builder().field(StrUtil.EMPTY).operator("cql").value(cql).build()));
        cqlBuilder.setLogic(LogicEnum.AND.getValue());
        return cqlBuilder;
    }

    @Builder
    @Getter
    @Setter
    static class Condition {

        private final String field;

        private final String operator;

        private final Object value;
    }
}
